#include "engine.h"
#include "texturemanager.h"
#include "animation.h"
#include "audio.h"
#include "font.h"
#include <math.h>
#include <time.h>

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

#include "scenes/mapscene.h"

CAnimation *g_ani;

CEngine *CEngine::m_pSingleton = NULL;

//===============================================================
// Initializes the game engine.
//===============================================================
CEngine *CEngine::Initialize(HWND hWnd, HINSTANCE hAppInstance, int nWidth, int nHeight)
{
	if (m_pSingleton)
		return NULL;

	m_pSingleton = new CEngine(hWnd, hAppInstance, nWidth, nHeight);
	return m_pSingleton;
}

//===============================================================
// De-initializes the engine.
//===============================================================
void CEngine::Deinitialize()
{
	if (m_pSingleton)
		delete m_pSingleton;

	m_pSingleton = NULL;
}

//===============================================================
// Initializes a new instance of the Engine class.
//===============================================================
CEngine::CEngine(HWND hWnd, HINSTANCE hAppInstance, int nWidth, int nHeight)
	:	m_hWnd(hWnd), 
		m_hAppInstance(hAppInstance), 
		m_nWidth(nWidth), 
		m_nHeight(nHeight), 
		m_bRunning(true)
{

	printf("Nickname: ");
	char szName[128];
	fgets(szName, 127, stdin);

	/* Initialize engine subsystems. */
	Initialize_Graphics();
	Initialize_Audio();


	printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
     printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
     printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));


	/* Start playing background music. */
	CAudio::Play("data/audio/music/theme.mid");

	/* Create a map scene. */
	m_pScene = new CMapScene();

	CMapScene *pScene = (CMapScene *)m_pScene;
	pScene->SetMap(new CMap("data/levels/test.pkl"));
	pScene->LoadTileset("data/tilesets/inside_house1.png", "data/tilesets/inside_house1.tdef");
	
	/* Load player animation. */
	g_ani = new CAnimation("data/ani.png", 4, 3, 32.0f, 48.0f, 0.2f);
	g_ani->SetMode(LOOP_ALTERNATE);



	/* Create a actor for the player. */
	m_pPlayer = new CActor(0, 0);
	m_pPlayer->SetMap(pScene->GetMap());
	m_pPlayer->SetAnimation(g_ani);
	m_pPlayer->SetX(2*32);
	m_pPlayer->SetY(5*32);
	m_pPlayer->SetName(szName);

	CActor *t = new CActor(0, 0);
	t->SetMap(pScene->GetMap());
	t->SetAnimation(new CAnimation("data/ani.png", 4, 3, 32.0f, 48.0f, 0.2f));
	t->SetX(3 * 32);
	t->SetY(5 * 32);
	t->GetAnimation()->SetMode(LOOP_ALTERNATE);
	t->GetAnimation()->Stop();

	pScene->SetTarget(m_pPlayer);
	pScene->AddActor(0, m_pPlayer);
	pScene->AddActor(1, t);
	for (u_int i = 2; i < 25; i++)
		pScene->AddActor(i, t);

	m_pFont = new CFont("Pokemon Pixel Font", 16);


}

//===============================================================
// Initializes the graphics subsystem of the engine.
//===============================================================
void CEngine::Initialize_Graphics()
{
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	m_pScreen = SDL_SetVideoMode(m_nWidth, m_nHeight, 32, SDL_OPENGL /*| SDL_FULLSCREEN*/); // *changed* 

	/* Set OpenGL up for 2D and disable the depth buffer. */
	glMatrixMode(GL_PROJECTION);
	glViewport(0, 0, m_nWidth, m_nHeight);
	glLoadIdentity();
	glOrtho(0, m_nWidth, m_nHeight, 0, 0, 1);
	glMatrixMode(GL_MODELVIEW);

	/* Configure OpenGL. */
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);

	/* Configure SDL. */
	//SDL_ShowCursor(SDL_DISABLE);
	SDL_EnableUNICODE(1);
	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

	/* Initialize OpenIL */
	ilInit();
}

//===============================================================
// Initializes the audio subsystem of the engine.
//===============================================================
void CEngine::Initialize_Audio()
{
	CAudio::Init();
}

//===============================================================
// Releases all resources allocated by the engine.
//===============================================================
CEngine::~CEngine()
{
	/* Destroy the OpenGL graphics context. */
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(m_hRc);

	ReleaseDC( m_hWnd, m_hDc );
}

static int  m_last_fps = 0;

//===============================================================
// Updates the engine.
//===============================================================
void CEngine::Think(int tick)
{
	static int  m_prev = 0;
	static int  m_fps = 0;
	static char m_fps_str[128];

	m_fps++;
	if ((tick - m_prev) >= 1000) 
	{
		m_prev = tick;
		m_last_fps = m_fps;
		m_fps = 0;
	}

	HandleInput();

	m_pPlayer->Think(tick); // update the player.
	Render();	
}

//===============================================================
// Handle mouse and keyboard I/O.
//===============================================================
void CEngine::HandleInput()
{
	if (KEY_DOWN(VK_UP)) m_pPlayer->Move(DIR_UP);
	else if (KEY_DOWN(VK_RIGHT)) m_pPlayer->Move(DIR_RIGHT);
	else if (KEY_DOWN(VK_DOWN)) m_pPlayer->Move(DIR_DOWN);
	else if (KEY_DOWN(VK_LEFT)) m_pPlayer->Move(DIR_LEFT);

	if (m_pPlayer->IsMoving())
	{
		if (!g_ani->IsAnimating())
			g_ani->Start();
	}
	else 
	{
		if (g_ani->IsAnimating())
			g_ani->Stop(1);
	}
}

//===============================================================
// Handles the specified SDL event.
//===============================================================
void CEngine::HandleEvent(SDL_Event *pEvent)
{
	switch (pEvent->type)
	{
		case SDL_MOUSEMOTION:
			break;

		case SDL_KEYDOWN:
			break;

		case SDL_KEYUP:
			break;

		case SDL_QUIT:
			Terminate();
			break;

		case SDL_VIDEORESIZE:
			break;
	}
}

//===============================================================
// Renders the current game state.
//===============================================================
void CEngine::Render()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	m_pScene->Render();

	m_pFont->Print(10, 10, "Pokemon Online v0.1 (%d fps)", m_last_fps);

	SDL_GL_SwapBuffers();
}
